import numpy, datetime
from collections import defaultdict
from sklearn.cross_validation import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.svm import SVC
from sklearn.neighbors import NearestCentroid
from sklearn.metrics import confusion_matrix, f1_score
from sklearn.metrics import classification_report
from sklearn.dummy import DummyClassifier
__author__ = 'panagiotis'


# create_ids = [i for i in xrange(0, 5000)]
start_time = datetime.datetime.now()

choices = ["Z", "N", "N", "N", "P", "P"]
# choices = [0, 1, 2, 3, 4, 5]
classes = sorted(list(set(choices)))

v_users = [[int(float(w)) for w in row] for row in [line.strip().split("\t") for line in open("scorevectors.csv", 'rb')]]
t_users = numpy.choose(v_users, choices)

v_books = [[float(w) for w in row] for row in [line.strip().split("\t") for line in open("weightvectors.csv", 'rb')]]

ratings = defaultdict(lambda: defaultdict(int))
for user in xrange(0, len(v_users)):
    for book in xrange(0, len(v_users[0])):
        if t_users[user][book] != choices[0]:
            ratings[user][book] = t_users[user][book]

cross_validated = defaultdict(list)

for state in xrange(0, 30):
    iteration_results = defaultdict(list)
    for user in ratings.keys():
        iteration_vectors = defaultdict(list)
        for book in ratings[user].keys():
            iteration_vectors['user'].append(v_users[user])
            iteration_vectors['book'].append(v_books[book])
            iteration_vectors['results'].append(ratings[user][book])
        this_user = defaultdict(list)
        this_user['train_user_vectors'], this_user['test_user_vectors'], \
            this_user['train_book_vectors'], this_user['test_book_vectors'],\
            this_user['train_targets'], this_user['test_correct'] = \
            train_test_split(iteration_vectors['user'], iteration_vectors['book'],
                             iteration_vectors['results'], random_state=state, test_size=0.3)
        clf = NearestCentroid()
        # clf = SVC(gamma=3, C=1)
        try:
            clf.fit(X=this_user['train_book_vectors'], y=this_user['train_targets'])
        except ValueError:
            clf = DummyClassifier(strategy="stratified")
            clf.fit(X=this_user['train_book_vectors'], y=this_user['train_targets'])
        this_user['predicted'] = clf.predict(X=this_user['test_book_vectors']).tolist()
        iteration_results['correct'] += this_user['test_correct']
        iteration_results['predicted'] += this_user['predicted']
        # unrated_predictions = clf.predict(v_books)
    iteration_results['f1_scores'] = f1_score(y_true=iteration_results['correct'],
                                              y_pred=iteration_results['predicted'],
                                              average=None)
    iteration_results['confusion'] = confusion_matrix(y_true=iteration_results['correct'],
                                                      y_pred=iteration_results['predicted'])
    iteration_results['report'] = classification_report(y_true=iteration_results['correct'],
                                                        y_pred=iteration_results['predicted'])
    cross_validated['correct'].append(iteration_results['correct'])
    cross_validated['predicted'].append(iteration_results['predicted'])
    cross_validated['f1_scores'].append(iteration_results['f1_scores'])
    cross_validated['confusion'].append(iteration_results['confusion'])
    cross_validated['report'].append(iteration_results['report'])


all_correct = []
for correct in cross_validated['correct']:
    all_correct += correct

all_predicted = []
for prediction in cross_validated['predicted']:
    all_predicted += prediction

for f1score in cross_validated['report']:
    print f1score

print classification_report(y_true=all_correct, y_pred=all_predicted)

print str(datetime.datetime.now() - start_time)
